package com.skl.base.model;

import android.os.Build;
import android.os.Handler;
import android.os.Looper;

import androidx.annotation.RequiresApi;

import com.skl.base.utils.GsonUtils;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentLinkedDeque;

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;

/**
 * 应用模块: model
 * 类描述: 基类抽象model
 */
public abstract class SuperBaseModel<T> {
    protected Handler mUIHandler = new Handler(Looper.getMainLooper());

    protected CompositeDisposable compositeDisposable;
    /**
     * 引用列队
     */
    protected ReferenceQueue<IBaseModelListener> mReferenceQueue;

    /**
     * 线程安全队列
     */
    protected ConcurrentLinkedDeque<WeakReference<IBaseModelListener>> mWeakReferenceDeque;

    public SuperBaseModel() {
        mReferenceQueue = new ReferenceQueue<>();
        mWeakReferenceDeque = new ConcurrentLinkedDeque<>();
    }

    /**
     * 对业务Model区分注册
     * @param listener
     */

    public void register(IBaseModelListener listener) {
        if (listener == null) {
            return;
        }
        synchronized (this) {
            //注册清理已被系统回收的对象
            Reference<? extends IBaseModelListener> releaseListener = null;
            while ((releaseListener = mReferenceQueue.poll()) != null) {
                mWeakReferenceDeque.remove(releaseListener);
            }

            //如果队列中还存在对象,就不用再次注册
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                for (WeakReference<IBaseModelListener> weakListener : mWeakReferenceDeque) {
                    IBaseModelListener listenerItem = weakListener.get();
                    if (listenerItem == listener) {
                        return;
                    }
                }
            }
            WeakReference<IBaseModelListener> weakReferenceListener = new WeakReference<>(listener, mReferenceQueue);
            mWeakReferenceDeque.add(weakReferenceListener);
        }
    }

    /**
     * 取消注册
     *
     * @param listener
     */
    public void unRegister(IBaseModelListener listener) {
        if (listener == null) {
            return;
        }
        synchronized (this) {
            for (WeakReference<IBaseModelListener> weakReferenceListener : mWeakReferenceDeque) {
                IBaseModelListener listenerItem = weakReferenceListener.get();
                if (listenerItem == listener) {
                    mWeakReferenceDeque.remove(weakReferenceListener);
                    break;
                }
            }
        }
    }

    /**
     * 需要缓存数据类型
     */
    protected Type getTclass() {
        return null;
    }

    /**
     * 该model的数据是否有apk预制的数据,如果有请返回
     */
    protected String getApkCache() {
        return null;
    }

    /**
     * 是否需要更新数据,默认每一次都需要更新
     *
     * @return true
     */
    protected boolean isNeedToUpData() {
        return true;
    }

    /**
     * 获取缓存数据并加载网络数据
     */
    public void getCacheDataAndLoad() {
        //如果有内置数据,先加载内置数据
        if (null != getApkCache()) {
            notifyCacheData((T) GsonUtils.fromLocalJson(getApkCache(),getTclass()));
            if (isNeedToUpData()) {
                load();
            }
        }

        //如果沒有加载网络数据
        load();
    }

    /**
     * 加载缓存数据
     */
    protected abstract void notifyCacheData(T data);
    /**
     * 加载网络数据
     */
    protected abstract void load();

    /**
     * 订阅对象管理
     * @param disposable
     */
    public void addDisposable(Disposable disposable){
        if (disposable == null) {
            return;
        }
        if (compositeDisposable == null) {
            compositeDisposable = new CompositeDisposable();
        }
        compositeDisposable.add(disposable);
    }

    /**
     * 取消所有订阅
     */
    public void cancelDisposable(){
        if (compositeDisposable != null && !compositeDisposable.isDisposed()) {
            compositeDisposable.isDisposed();
        }
    }
}

